/**
 * 
 * @brief  bsp_mipi.c
 * @param  None
 * 
 * @author xhq
 * @date   2024/11/07
 * 
 */
/* include */
#include "util_factory.h"
#include "bsp_mipi.h"
#include "util_factory.h"

/* define */
#define BSP_MIPI_DEBUG       0

/* typedef */


/* global variebles */
mipi_recv_info_type g_mipi_recv_info = {
    .mipi_num = MIPI_CHANNEL_MAX,
    .mipi_thread_handle_num = MIPI_RECV_THREAD_NUM,
    .mipi_input_fram_num = 10,
    .mipi_clk_freq = 400000000,
    .mipi_fram_len = FRAME_LEN,
    .mipi_index[0].fd = -1,
    .mipi_index[0].dev_name = "/dev/skrl_mipi0",
    .mipi_index[0].mipi_sigact.sa_sigaction = (void *)dma_signal_callback_mipi0,
    .mipi_index[0].mipi_sigact.sa_flags = SA_RESTART|SA_SIGINFO,
    .mipi_index[1].fd = -1,
    .mipi_index[1].dev_name = "/dev/skrl_mipi1",
    .mipi_index[1].mipi_sigact.sa_sigaction = (void *)dma_signal_callback_mipi1,
    .mipi_index[1].mipi_sigact.sa_flags = SA_RESTART|SA_SIGINFO,
    .mipi_index[2].fd = -1,
    .mipi_index[2].dev_name = "/dev/skrl_mipi2",
    .mipi_index[2].mipi_sigact.sa_sigaction = (void *)dma_signal_callback_mipi2,
    .mipi_index[2].mipi_sigact.sa_flags = SA_RESTART|SA_SIGINFO,
    .mipi_index[3].fd = -1,
    .mipi_index[3].dev_name = "/dev/skrl_mipi3",
    .mipi_index[3].mipi_sigact.sa_sigaction = (void *)dma_signal_callback_mipi3,
    .mipi_index[3].mipi_sigact.sa_flags = SA_RESTART|SA_SIGINFO,
};

// 临时存放即将存入SSD中的mipi数据的空间
uint8_t g_temp_mipi[MIPI_CHANNEL_MAX][MIPI_RECV_THREAD_NUM][FRAME_LEN] = {0};

// 0--前后半帧均未收到；1--已收到半帧数据；2--已收到完整的一帧数据；
uint32_t g_frame_integrity = 0;

/* function */
/**
 * @brief mipi模块初始化
 * 
 * @param None ：
 * 
 * @return uint32_t ：0：正常，非0：错误代码
 * 
 * @note：
 */
uint32_t bsp_mipi_init(void)
{
    int l_int_info = 0, l_memmap_fd = -1;
    int32_t  l_int32_err = 0;
    uint32_t l_u32_ret = 0;
    uint32_t l_u32_i = 0, l_u32_j = 0;
    uint32_t l_u32_thread_num = 0;

    /* 初始化内存地址映射变量 */
    uint64_t l_u64_share_mem_address = 0xA7000000;
    uint64_t l_u64_share_mem_size    = 0x01000000;    // 16M

    l_memmap_fd = open("/dev/mem", O_RDWR | O_SYNC);
    if (l_memmap_fd == -1)
    {
        goto error;
    }

    /* 映射文件到内存 */
    g_fram_raw_data_info.pu8_mmap = mmap(NULL, l_u64_share_mem_size, PROT_READ | PROT_WRITE, MAP_SHARED, l_memmap_fd, l_u64_share_mem_address);
    if (g_fram_raw_data_info.pu8_mmap == MAP_FAILED) 
    {
        goto error;
    }

    /* 分配2路mipi的逻辑地址 */
    g_mipi_recv_info.mipi_index[0].pu8_mmap = g_fram_raw_data_info.pu8_mmap;
    g_mipi_recv_info.mipi_index[1].pu8_mmap = g_fram_raw_data_info.pu8_mmap + FRAME_LEN;   // 偏移3MB

    /* 1.初始化信号量和创建线程 */
    for (l_u32_i = 0; l_u32_i < g_mipi_recv_info.mipi_num; l_u32_i++)
    {
        for (l_u32_j = 0; l_u32_j < g_mipi_recv_info.mipi_thread_handle_num; l_u32_j++)
        {
            /* 初始化数据处理信号量 */
            if (sem_init(&g_mipi_recv_info.mipi_index[l_u32_i].info[l_u32_j].sem, 0, 0) != 0) 
            {
                SET_ERROR_CODE(l_u32_ret, 0);
                goto error;
            }

            /* 线程序号 */
            l_u32_thread_num = ((l_u32_i << 16) | l_u32_j);

            /* 创建基础数据处理线程 */
            if (pthread_create(&g_mipi_recv_info.mipi_index[l_u32_i].info[l_u32_j].thread_pid, NULL, mipi_recv_thread, &l_u32_thread_num) != 0)
            {
                SET_ERROR_CODE(l_u32_ret, 1);
                goto error;
            }

            usleep(10000);   // 等待线程运行后继续创建
        }
    }

    /* 2.初始化mipi信号及打开设备节点 */
    for (l_u32_i = 0; l_u32_i < g_mipi_recv_info.mipi_num; l_u32_i++)
    {
        /* 初始化mipi驱动端信号 */
        sigemptyset(&g_mipi_recv_info.mipi_index[l_u32_i].mipi_sigact.sa_mask);
        if (sigaction(SIGN_SIGRTMIN + l_u32_i, &g_mipi_recv_info.mipi_index[l_u32_i].mipi_sigact, NULL) < 0)
        {
            SET_ERROR_CODE(l_u32_ret, 2);
            goto error;
        }

        /* 打开设备节点 */
        g_mipi_recv_info.mipi_index[l_u32_i].fd = open(g_mipi_recv_info.mipi_index[l_u32_i].dev_name, O_RDWR);
        if (g_mipi_recv_info.mipi_index[l_u32_i].fd == -1)
        {
            SET_ERROR_CODE(l_u32_ret, 3);
            goto error;
        }

        /* 初始化驱动的信号 */
        l_int_info = getpid();
        if (ioctl(g_mipi_recv_info.mipi_index[l_u32_i].fd, CMD_INIT_SINGNAL_INFO_CMD, &l_int_info) != 0)
        {
            SET_ERROR_CODE(l_u32_ret, 4);
            goto error;
        }

        /* 初始化mipi的clk时钟频率 */
        printf("mipi clock :%d,fram_len:%d\n",g_mipi_recv_info.mipi_clk_freq,g_mipi_recv_info.mipi_fram_len);
        if (ioctl(g_mipi_recv_info.mipi_index[l_u32_i].fd, CMD_SET_MIPI_FREQ, &g_mipi_recv_info.mipi_clk_freq) != 0)
        {
            SET_ERROR_CODE(l_u32_ret, 5);
            goto error;
        }    

        /* 初始化mipi的设置mipi的buf长度 */
        if (ioctl(g_mipi_recv_info.mipi_index[l_u32_i].fd, CMD_SET_FRAME_DATA_LEN, &g_mipi_recv_info.mipi_fram_len) != 0)
        {
            SET_ERROR_CODE(l_u32_ret, 6);
            goto error;
        }   

        /* 清空dma queue 的list*/
        if (ioctl(g_mipi_recv_info.mipi_index[l_u32_i].fd, CMD_CLEAR_DMA_QUEUE, &l_int_info) != 0)
        {
            SET_ERROR_CODE(l_u32_ret, 7);
            goto error;
        }  

        /* 释放缓存--临时处理措施 */
        l_int_info = 0;
        if (ioctl(g_mipi_recv_info.mipi_index[l_u32_i].fd, CMD_RELEASE_DMA_BFU_ALLOC, &l_int_info) != 0)
        {
            SET_ERROR_CODE(l_u32_ret, 8);
            goto error;
        }

        /* 申请缓存 */
        l_int_info = MIPI_RECV_THREAD_NUM;      // 缓存
        if (ioctl(g_mipi_recv_info.mipi_index[l_u32_i].fd,CMD_INIT_DMA_BUF_ALLOC,&l_int_info) != 0)
        {
            SET_ERROR_CODE(l_u32_ret, 9);
            goto error;
        }

        // //测试打印物理地址
        // if (ioctl(g_mipi_recv_info.mipi_index[l_u32_i].fd,CMD_TEST_PRINTK_ALLOC_INFO,&l_int_info) != 0)
        // {
        //     SET_ERROR_CODE(l_u32_ret, 9);
        //     goto error;
        // }




 //       printf("*****dphy status :0x%.8x****\n",ioctl(g_mipi_recv_info.mipi_index[l_u32_i].fd,CMD_READ_DPHY_STATUS,&l_int_info));

    }

    /* 初始化应用层存储mipi数据的内存空间，从堆上申请 */
    for (size_t i = 0; i < MIPI_CHANNEL_MAX; i++)
    {

            for (size_t l = 0; l < QUEUE_RECV_DATA_NUM; l++)
            {
                g_mipi_to_up_queue[i].m_u8buffer[l] = (uint8_t *)malloc(QUEUE_EACH_UNIT_MAX_LEN);
                if (g_mipi_to_up_queue[i].m_u8buffer[l] == NULL)
                {
                    printf("mipi data save memory malloc failed.i = %u, l = %u\n", i, l);
                    SET_ERROR_CODE(l_u32_ret, 10);
                    goto error;
                }
                memset(g_mipi_to_up_queue[i].m_u8buffer[l], 0x00, QUEUE_EACH_UNIT_MAX_LEN);
            }
    }

    RETURN_ERROR_CODE(l_u32_ret, __func__);
error:
    /* 解除映射 */
    // if (g_fram_raw_data_info.pu8_mmap != NULL)
    // {
    //     munmap(g_fram_raw_data_info.pu8_mmap, l_u64_share_mem_size);
    // }
    if (l_memmap_fd != -1)
    {
        close(l_memmap_fd);
    }
    bsp_mipi_deinit();
    RETURN_ERROR_CODE(l_u32_ret, __func__);
}
/**
 * @brief mipi模块去初始化
 * 
 * @param None ：
 * 
 * @return uint32_t ：0：正常，非0：错误代码
 * 
 * @note：
 */
uint32_t bsp_mipi_deinit(void)
{
    int l_int_info = 0;
    uint32_t l_u32_ret = 0;
    uint32_t l_u32_i = 0;

    for (l_u32_i = 0; l_u32_i < MIPI_CHANNEL_MAX; l_u32_i++)
    {
        /* 释放缓存及关闭设备 */
        if (g_mipi_recv_info.mipi_index[l_u32_i].fd != -1)
        {
            /* 释放缓存 */
            ioctl(g_mipi_recv_info.mipi_index[l_u32_i].fd, CMD_RELEASE_DMA_BFU_ALLOC, &l_int_info);

            /* 关闭fd */
            close(g_mipi_recv_info.mipi_index[l_u32_i].fd);
        }
    }

    error:
    RETURN_ERROR_CODE(l_u32_ret, __func__);
}
/**
 * @brief mipi模块读数据
 * 
 * @param None ：
 * 
 * @return uint32_t ：0：正常，非0：错误代码
 * 
 * @note：
 */
uint32_t bsp_mipi_read(void)
{    
    uint32_t l_u32_ret = 0;

    error:
    RETURN_ERROR_CODE(l_u32_ret, __func__);
}
/**
 * @brief mipi模块写数据
 * 
 * @param None ：
 * 
 * @return uint32_t ：0：正常，非0：错误代码
 * 
 * @note：
 */
uint32_t bsp_mipi_write(void)
{
    uint32_t l_u32_ret = 0;

    error:
    RETURN_ERROR_CODE(l_u32_ret, __func__);
}

/**
 * @brief mipi模块开启dma
 * 
 * @param l_u32_first_flag ：1-首次上电， 0-非首次上电
 * 
 * @return uint32_t ：0：正常，非0：错误代码
 * 
 * @note：
 */
uint32_t  bsp_mipi_start_dma(int index)
{
    int l_int_info = 0;
    uint32_t l_u32_ret = 0;
    uint32_t l_u32_i,l_u32_j = 0;

    if (ioctl(g_mipi_recv_info.mipi_index[index].fd, CMD_INIT_TDA4_SHIM_DPHY_CSIRX, &l_int_info) != 0)   //shim 
    {
        SET_ERROR_CODE(l_u32_ret, 0);
        goto error;
    }

    if (ioctl(g_mipi_recv_info.mipi_index[index].fd, CMD_START_CSI_RX_IF, &l_int_info) != 0)   //开dphy 
    {
        SET_ERROR_CODE(l_u32_ret, 1);
        goto error;
    }

    if (ioctl(g_mipi_recv_info.mipi_index[index].fd, CMD_START_DMA_DATA_INIO_BUF, &l_int_info) != 0)     //dma go
    {
        SET_ERROR_CODE(l_u32_ret, 2);
        goto error;
    }

    error:
        RETURN_ERROR_CODE(l_u32_ret, __func__);
}


uint8_t g_mipi_data_temp[4][2 * 1024 *1024];
/**
 * @brief 读取固定的mipi数据文件，存到全局变量当中
 * 
 * @param mipi_file_path ：mipi文件路径
 * 
 * @return uint32_t ：0：正常，非0：失败
 * 
 * @note：
 */
uint32_t read_mipi_file(const char *mipi_file_path, uint8_t *p_out_put)
{
    FILE *fp = NULL;
    uint32_t l_u32read_num = 0;
    long file_size = 0;

    fp = fopen(mipi_file_path, "rb");
    if (!fp)
    {
        perror("read_mipi_file, Failed to open file");
        return 1;
    }

    fseek(fp, 0 , SEEK_END);
    file_size = ftell(fp);
    rewind(fp);


    l_u32read_num = fread((void *)p_out_put, sizeof(char), sizeof(g_mipi_data_temp[1]), fp);
    fclose(fp);
    if (l_u32read_num != sizeof(g_mipi_data_temp[1]))
    {
        fprintf(stderr, "Error: Only read %zu bytes, expected %zu\n", l_u32read_num, sizeof(g_mipi_data_temp[1]));

        return 1;
    }

    return 0;
    
}


/**
 * @brief 读取两个mipi数据文件，存到对应的全局变量当中
 * 
 * @param pthread_idx ： 线程索引
 * 
 * @return uint32_t ：0：正常，非0：失败
 * 
 * @note：
 */
uint32_t load_mipi_file_to_ram(uint16_t p_thread)
{
    uint32_t l_u32ret = 0;

    switch (p_thread)
    {
        case 0:
        {
            l_u32ret = read_mipi_file("/home/flash_data_0.bin", g_mipi_data_temp[0]);
            if (l_u32ret)
            {
                printf("read mipi file flash_data_0 failed\n");
                return 1;
            }
            break;
        }
        case 1:
        {
            l_u32ret = read_mipi_file("/home/flash_data_1.bin", g_mipi_data_temp[1]);
            if (l_u32ret)
            {
                printf("read mipi file flash_data_1 failed\n");
                return 1;
            }
            break;
        }
        case 2:
        {
            l_u32ret = read_mipi_file("/home/flash_data_2.bin", g_mipi_data_temp[2]);
            if (l_u32ret)
            {
                printf("read mipi file flash_data_2 failed\n");
                return 1;
            }
            break;
        }
        case 3:
        {
            l_u32ret = read_mipi_file("/home/flash_data_3.bin", g_mipi_data_temp[3]);
            if (l_u32ret)
            {
                printf("read mipi file flash_data_3 failed\n");
                return 1;
            }
            break;
        }
        default:
            printf("load_mipi_file_to_ram pthread idx invalid.\n");
            break;
    }
    return 0;
}

// 对比两个数组中的num个元素是否一致
void check_uint8_arry(char *datadsc,uint8_t *a,uint8_t *b,int num)
{
    int i;
    for(i=0;i<num;i++){
        if(a[i] != b[i]){
            printf(" %s[%d]:%d-%d unequal\n",datadsc,i,a[i],b[i]);
        }
    }
}


// 获取UCT时间，的秒和微秒部分，并将其存储到8字节数组中
void get_utc_time(uint8_t *p_buf)
{
    /* 入参检查 */
    if (p_buf == NULL)
    {
        printf("get_utc_time param err.\n");
        return;
    }
    
    struct timeval tv;
    uint32_t sec = 0, usec = 0;

    /* 获取当前时间 */
    gettimeofday(&tv, NULL); 

    // 转换秒和微秒为32位无符号整数
    sec = (uint32_t)tv.tv_sec;
    usec = (uint32_t)tv.tv_usec;

    // // 默认为小端模式，这里进行大端序存储（网络字节序）
    // sec = htonl(sec);
    // usec = htonl(usec);

    // 复制数据到缓冲区
    memcpy(p_buf, &sec, sizeof(sec));
    memcpy(p_buf + sizeof(sec), &usec, sizeof(usec));
}

/**
 * @brief mipi接收数据线程
 * 
 * @param None ：
 * 
 * @return None
 * 
 * @note：
 */ 
void *mipi_recv_thread(void *param)
{
    uint8_t  *l_u8_pmap_buf = NULL;
    uint32_t l_u32_tread_num = *((uint32_t *)param);
    struct timespec l_timespec_start = {0};
    struct timespec l_timespec_end = {0};
    struct timespec l_timespec_end_1 = {0};
    struct timespec l_timespec_end_2 = {0};
    uint32_t l_running_time_us = 0;
    uint32_t l_running_time_us_1 = 0;
    uint32_t l_running_time_us_2 = 0;
    uint32_t l_running_time_ms = 0;
    uint32_t l_waiting_time_ms = 0;
    uint32_t buf_num;
    uint32_t info;
    uint32_t l_u32_mipi_req_num = 0;
    uint32_t l_u32_i = 0;
    uint32_t judge_value=0;

    rpmsg_status_param_type *l_rpmsg_status_param = get_rpmsg_status_param();
    rpmsg_config_param_type *l_rpmsg_config_param = get_rpmsg_config_param();

    /* 获取对应的mipi通道号和接收线程序号 */
    uint16_t l_u16_mipi_channel_i  = (uint16_t)((l_u32_tread_num & 0xffff0000) >> 16);     // mipi通道号 0, 1
    uint16_t l_u16_mipi_recv_num_j = (uint16_t)(l_u32_tread_num & 0x0000ffff);             // mipi接收线程数 0～3
    info = l_u16_mipi_recv_num_j;
    printf("mipi通道号:%d,mipi接收线程数:%d\n",l_u16_mipi_channel_i,l_u16_mipi_recv_num_j);

    while(1)
    {
        /* 等待信号量 */
        sem_wait(&g_mipi_recv_info.mipi_index[l_u16_mipi_channel_i].info[l_u16_mipi_recv_num_j].sem);

        /* 保存数据开始计时 */
        // memcpy(&l_timespec_end,&l_timespec_start,sizeof(struct timespec));
        // clock_gettime(CLOCK_MONOTONIC_RAW, &l_timespec_start);
        // l_waiting_time_ms  = (l_timespec_start.tv_sec - l_timespec_end.tv_sec) * 1000 + 
        //      (l_timespec_start.tv_nsec - l_timespec_end.tv_nsec) / 1000000;
      

        /* debug */
        // printf("mipi_channel is %d, pthread_id is %d, pthread recv cnt is %d\n.",
        //         l_u16_mipi_channel_i,l_u16_mipi_recv_num_j,g_mipi_recv_info.mipi_index[l_u16_mipi_channel_i].fram_count);
        // printf("%d %d %d\n", l_u16_mipi_channel_i,l_u16_mipi_recv_num_j,g_mipi_recv_info.mipi_index[l_u16_mipi_channel_i].fram_count);
        // if ((g_mipi_recv_info.mipi_index[l_u16_mipi_channel_i].fram_count % 100) == 0)
        // {
            // printf("%d\n", g_mipi_recv_info.mipi_index[l_u16_mipi_channel_i].fram_count);
        // }
        //printf("%d,%d %d:%d\n",l_u16_mipi_channel_i,l_u16_mipi_recv_num_j,
        //    g_mipi_to_up_queue[l_u16_mipi_channel_i].fifoin, g_mipi_to_up_queue[l_u16_mipi_channel_i].fifoout);

        /* 映射内存空间 */
        buf_num = l_u16_mipi_recv_num_j;
        ioctl(g_mipi_recv_info.mipi_index[l_u16_mipi_channel_i].fd, CMD_SET_MMAP_BUF_INDEX, &buf_num);
	    l_u8_pmap_buf = mmap(NULL, FRAME_LEN, PROT_READ, MAP_SHARED, g_mipi_recv_info.mipi_index[l_u16_mipi_channel_i].fd, 0);

        /* 保存数据开始计时 */
        // clock_gettime(CLOCK_MONOTONIC_RAW, &l_timespec_start);

        /* 将mipi原始数据保存mipi数据到ssd */
        // lib_memcpy(g_temp_mipi[l_u16_mipi_channel_i][l_u16_mipi_recv_num_j], l_u8_pmap_buf, FRAME_LEN);
        /* 保存数据结束，统计操作耗时 */
        // clock_gettime(CLOCK_MONOTONIC_RAW, &l_timespec_end);
        // l_running_time_us = (l_timespec_end.tv_sec - l_timespec_start.tv_sec) * 1000000 + 
        //                         (l_timespec_end.tv_nsec - l_timespec_start.tv_nsec) / 1000;
        // save_data_to_ssd(g_temp_mipi[l_u16_mipi_channel_i][l_u16_mipi_recv_num_j], FRAME_LEN, l_u32_tread_num, g_mipi_recv_info.mipi_index[l_u16_mipi_channel_i].fram_count);

        /* 保存数据结束，统计操作耗时 */
        // clock_gettime(CLOCK_MONOTONIC_RAW, &l_timespec_end_1);
        // l_running_time_us_1 = (l_timespec_end_1.tv_sec - l_timespec_start.tv_sec) * 1000000 + 
        //                         (l_timespec_end_1.tv_nsec - l_timespec_start.tv_nsec) / 1000;
        
        /* 保存数据到内存当中 */
        // 根据要求保存要发送的mipi数据
        if (g_mipi_data_upload_flag)
        {
            // 各线程根据要求将即将发送至上位机的mipi数据保存到相应的队列当中
            pthread_mutex_lock(&g_Mutext_mipi_send_up[l_u16_mipi_channel_i]);
            get_utc_time(g_mipi_to_up_queue[l_u16_mipi_channel_i].m_utctime[g_mipi_to_up_queue[l_u16_mipi_channel_i].fifoin]);
            lib_memcpy(g_mipi_to_up_queue[l_u16_mipi_channel_i].m_u8buffer[g_mipi_to_up_queue[l_u16_mipi_channel_i].fifoin],l_u8_pmap_buf, FRAME_LEN);
            g_mipi_to_up_queue[l_u16_mipi_channel_i].m_u32length[g_mipi_to_up_queue[l_u16_mipi_channel_i].fifoin] = FRAME_LEN;
            g_mipi_to_up_queue[l_u16_mipi_channel_i].m_i8fd[g_mipi_to_up_queue[l_u16_mipi_channel_i].fifoin] = g_socket_info[SOCKET_CMD_TYPE].fd;
            g_mipi_to_up_queue[l_u16_mipi_channel_i].m_u8valid[g_mipi_to_up_queue[l_u16_mipi_channel_i].fifoin] = VALID_VALUE;
            g_mipi_to_up_queue[l_u16_mipi_channel_i].fifoin = (g_mipi_to_up_queue[l_u16_mipi_channel_i].fifoin + 1)%QUEUE_RECV_DATA_NUM;
            pthread_mutex_unlock(&g_Mutext_mipi_send_up[l_u16_mipi_channel_i]);
            // 确保两个半帧的mipi原始数据都已保存，并且进行计数，计数足够后，停止保存
            pthread_mutex_lock(&g_Mutext_mipi_recv_cnt);
            g_recv_mipi_half_frame_cnt++;
            // 要求上传mipi数据，且收到第一帧完整的mipi数据时，抛信号量
            if ((g_recv_mipi_half_frame_cnt > 1) && ((g_recv_mipi_half_frame_cnt % 2) == 0))
            {
                sem_post(&g_mipi_send_up_semaphore);
            }
            // printf("g_recv_mipi_half_frame_cnt = %u.\n", g_recv_mipi_half_frame_cnt);
            if ((g_recv_mipi_half_frame_cnt / 2) >= g_mipi_req_info.req_mipi_num)
            {
                g_mipi_data_upload_flag = 0;
                // printf("g_recv_mipi_frame_cnt = %u, req_mipi_num = %u, get upload mipi data over.\n", g_recv_mipi_frame_cnt, g_recv_mipi_frame_cnt);
            }
            pthread_mutex_unlock(&g_Mutext_mipi_recv_cnt);
        }

        /* 数据传给dsp */
        if (l_u16_mipi_channel_i < (l_u16_mipi_channel_i ^ 1))
        {
            //  memcpy((uint64_t *)g_mipi_recv_info.mipi_index[0].pu8_mmap, (uint64_t *)l_u8_pmap_buf, FRAME_LEN);
            lib_memcpy(g_mipi_recv_info.mipi_index[0].pu8_mmap,l_u8_pmap_buf,FRAME_LEN);
            // __builtin_memcpy((uint64_t *)g_mipi_recv_info.mipi_index[0].pu8_mmap,l_u8_pmap_buf,FRAME_LEN);
            //lib_memcpy(test_buf,l_u8_pmap_buf,FRAME_LEN);
            // sync();
            // check_uint8_arry("lib_memcpy 0",l_u8_pmap_buf,g_mipi_recv_info.mipi_index[0].pu8_mmap,10);
            // check_uint8_arry("lib_memcpy 0 tail 10",&l_u8_pmap_buf[FRAME_LEN-11],&g_mipi_recv_info.mipi_index[0].pu8_mmap[FRAME_LEN-11],10);
        }
        else
        {
            //  memcpy((uint64_t *)g_mipi_recv_info.mipi_index[1].pu8_mmap, (uint64_t *)l_u8_pmap_buf, FRAME_LEN);
            lib_memcpy(g_mipi_recv_info.mipi_index[1].pu8_mmap,l_u8_pmap_buf,FRAME_LEN);
            // __builtin_memcpy((uint64_t *)g_mipi_recv_info.mipi_index[1].pu8_mmap,l_u8_pmap_buf,FRAME_LEN);
            // lib_memcpy(&test_buf[FRAME_LEN],l_u8_pmap_buf,FRAME_LEN);
            // sync();
            // check_uint8_arry("lib_memcpy 1",l_u8_pmap_buf,g_mipi_recv_info.mipi_index[1].pu8_mmap,10);
            // check_uint8_arry("lib_memcpy 1 tail 10",&l_u8_pmap_buf[FRAME_LEN-11],&g_mipi_recv_info.mipi_index[1].pu8_mmap[FRAME_LEN-11],10);
        }

        pthread_mutex_lock(&g_Mutext_mipi_recv_cnt);          
        g_frame_integrity++;
        switch (g_frame_integrity)
        {
            case 1:
            {
                /* code */
                break;
            }
            case 2:
            {
                //发送给dsp的时间
                clock_gettime(CLOCK_MONOTONIC_RAW, &g_timespec_start); 
                /* 发送通知至dsp */
                dsp_rpmsg_set_data_pro_msg();
                g_frame_integrity = 0;
                break;
            }
            default:
                printf("g_frame_integrity err, g_frame_integrity = %u.\n", g_frame_integrity);
                g_frame_integrity = 0;
                break;
        }
        pthread_mutex_unlock(&g_Mutext_mipi_recv_cnt);
        
        /*******************************
        //测试lib_memcpy(dst,src)数据是否一致
        if (l_u16_mipi_channel_i < (l_u16_mipi_channel_i ^ 1)){
            if((test_buf[0] == l_u8_pmap_buf[0])&&(test_buf[10] == l_u8_pmap_buf[10])
                &&(test_buf[100] == l_u8_pmap_buf[100])&&(test_buf[1000] == l_u8_pmap_buf[1000])
                &&(test_buf[FRAME_LEN-100] == l_u8_pmap_buf[FRAME_LEN-100])&&(test_buf[FRAME_LEN-10] == l_u8_pmap_buf[FRAME_LEN-10]))
            {
                judge_value = 1;
            }   
        }
        else
        {
            if((test_buf[FRAME_LEN+0] == l_u8_pmap_buf[0])&&(test_buf[FRAME_LEN+10] == l_u8_pmap_buf[10])
                &&(test_buf[FRAME_LEN+100] == l_u8_pmap_buf[100])&&(test_buf[FRAME_LEN+1000] == l_u8_pmap_buf[1000])
                &&(test_buf[2*FRAME_LEN-100] == l_u8_pmap_buf[FRAME_LEN-100])&&(test_buf[2*FRAME_LEN-10] == l_u8_pmap_buf[FRAME_LEN-10])
                &&(test_buf[2*FRAME_LEN-1] == l_u8_pmap_buf[FRAME_LEN-1]))
            {
                judge_value = 2;
            }   
        }
        ******************************************************************* */

        /* 取消内存映射 */
        if (l_u8_pmap_buf != NULL)
        {
            munmap(l_u8_pmap_buf, FRAME_LEN);
        }

        /* 保存数据结束，统计操作耗时 */
        // clock_gettime(CLOCK_MONOTONIC_RAW, &l_timespec_end_2);
        // l_running_time_us_2 = (l_timespec_end_2.tv_sec - l_timespec_start.tv_sec) * 1000000 + 
        //                         (l_timespec_end_2.tv_nsec - l_timespec_start.tv_nsec) / 1000;
        // printf("%d %d %d %uus %ums\n", l_u16_mipi_channel_i,l_u16_mipi_recv_num_j,
        //         g_mipi_recv_info.mipi_index[l_u16_mipi_channel_i].fram_count,l_running_time_us,l_running_time_us/1000);
        // printf("%d %d %d %uus %ums %ums %ums\n", l_u16_mipi_channel_i,l_u16_mipi_recv_num_j,
        //     g_mipi_recv_info.mipi_index[l_u16_mipi_channel_i].fram_count,l_running_time_us,l_running_time_us/1000, l_running_time_us_1/1000, l_running_time_us_2/1000);

    }
}
/**
 * @brief mipi0 dma信号中断回调函数
 * 
 * @param None ：
 * 
 * @return None
 * 
 * @note：
 */
void *dma_signal_callback_mipi0(int signum, siginfo_t *info, void *context)
{
    /* info->si_errno  数据buff ：0~3; info->si_code  mipi通道号（2路mipi）*/
    uint32_t l_u32_i = info->si_errno;
    
//    printf("mipi0:%d, %d\n", g_mipi_recv_info.mipi_index[0].fram_count, l_u32_i); 

    /* 设置下一次接收缓存区（有采集帧数上限） */
    // if (MIPI_RECV_THREAD_NUM+g_mipi_recv_info.mipi_index[0].fram_count++ < g_mipi_recv_info.mipi_index[0].need_handle_fram_num)
    {
        ioctl(g_mipi_recv_info.mipi_index[0].fd, CMD_SET_DMA_BUF_INDEX, &l_u32_i);
    }

    // if((g_mipi_recv_info.mipi_index[0].need_handle_fram_num > 0)&&(g_mipi_recv_info.mipi_index[0].fram_count < g_mipi_recv_info.mipi_index[0].need_handle_fram_num))
	{
        g_mipi_recv_info.mipi_index[0].fram_count++;
	}

    /* 释放信号量 */
    sem_post(&g_mipi_recv_info.mipi_index[0].info[l_u32_i].sem);
}

/**
 * @brief mipi1 dma信号中断回调函数
 * 
 * @param None ：
 * 
 * @return None
 * 
 * @note：
 */
void *dma_signal_callback_mipi1(int signum, siginfo_t *info, void *context)
{
    /* info->si_errno  数据buff ：0~3; info->si_code  mipi通道号（2路mipi）*/
    uint32_t l_u32_i = info->si_errno;

    /* 设置下一次接收缓存区 */
    // if (MIPI_RECV_THREAD_NUM+g_mipi_recv_info.mipi_index[1].fram_count++ < g_mipi_recv_info.mipi_index[1].need_handle_fram_num)
    {
        ioctl(g_mipi_recv_info.mipi_index[1].fd, CMD_SET_DMA_BUF_INDEX, &l_u32_i);
    }  
    // printf("mipi1:%d, %d\n", g_mipi_recv_info.mipi_index[1].fram_count, l_u32_i);

    // if((g_mipi_recv_info.mipi_index[1].need_handle_fram_num > 0)&&(g_mipi_recv_info.mipi_index[1].fram_count < g_mipi_recv_info.mipi_index[1].need_handle_fram_num))
	{
        g_mipi_recv_info.mipi_index[1].fram_count++;
	}

    /* 释放信号量 */
    sem_post(&g_mipi_recv_info.mipi_index[1].info[l_u32_i].sem);
}

/**
 * @brief mipi2 dma信号中断回调函数
 * 
 * @param None ：
 * 
 * @return None
 * 
 * @note：
 */
void *dma_signal_callback_mipi2(int signum, siginfo_t *info, void *context)
{
    /* info->si_errno  数据buff ：0~3; info->si_code  mipi通道号（2路mipi）*/
    uint32_t l_u32_i = info->si_errno;

    /* 设置下一次接收缓存区 */
    // if (MIPI_RECV_THREAD_NUM+g_mipi_recv_info.mipi_index[2].fram_count++ < g_mipi_recv_info.mipi_index[2].need_handle_fram_num)
    {
        ioctl(g_mipi_recv_info.mipi_index[2].fd, CMD_SET_DMA_BUF_INDEX, &l_u32_i);
    }  
    // printf("mipi1:%d, %d\n", g_mipi_recv_info.mipi_index[1].fram_count, l_u32_i);

    // if((g_mipi_recv_info.mipi_index[2].need_handle_fram_num > 0)&&(g_mipi_recv_info.mipi_index[2].fram_count < g_mipi_recv_info.mipi_index[2].need_handle_fram_num))
	{
        g_mipi_recv_info.mipi_index[2].fram_count++;
	}

    /* 释放信号量 */
    sem_post(&g_mipi_recv_info.mipi_index[2].info[l_u32_i].sem);
}

/**
 * @brief mipi3 dma信号中断回调函数
 * 
 * @param None ：
 * 
 * @return None
 * 
 * @note：
 */
void *dma_signal_callback_mipi3(int signum, siginfo_t *info, void *context)
{
    /* info->si_errno  数据buff ：0~3; info->si_code  mipi通道号（2路mipi）*/
    uint32_t l_u32_i = info->si_errno;

    /* 设置下一次接收缓存区 */
    // if (MIPI_RECV_THREAD_NUM+g_mipi_recv_info.mipi_index[3].fram_count++ < g_mipi_recv_info.mipi_index[3].need_handle_fram_num)
    {
        
        ioctl(g_mipi_recv_info.mipi_index[3].fd, CMD_SET_DMA_BUF_INDEX, &l_u32_i);
    }  
    // printf("mipi1:%d, %d\n", g_mipi_recv_info.mipi_index[1].fram_count, l_u32_i);

    // if((g_mipi_recv_info.mipi_index[3].need_handle_fram_num > 0)&&(g_mipi_recv_info.mipi_index[3].fram_count < g_mipi_recv_info.mipi_index[3].need_handle_fram_num))
	{
        g_mipi_recv_info.mipi_index[3].fram_count++;
	}

    /* 释放信号量 */
    sem_post(&g_mipi_recv_info.mipi_index[3].info[l_u32_i].sem);
}
